// test schur decomposition
import assert from 'assert'
import math from '../../../../src/defaultInstance.js'
import sinon from 'sinon'

describe('sylvester', function () {
  it('should solve sylvester equation of order 5 with Arrays', function () {
    assert.ok(math.norm(math.subtract(math.sylvester([
      [-5.3, -1.4, -0.2, 0.7],
      [-0.4, -1.0, -0.1, -1.2],
      [0.3, 0.7, -2.5, 0.7],
      [3.6, -0.1, 1.4, -2.4]
    ], [
      [1.1, -0.3, -0.9, 0.8, -2.5],
      [-0.6, 2.6, 0.2, 0.4, 1.3],
      [0.4, -0.5, -0.2, 0.2, -0.1],
      [-0.4, -1.9, -0.2, 0.5, 1.4],
      [0.4, -1.0, -0.1, -0.8, -1.3]
    ], [
      [1.4, 1.1, -1.9, 0.1, 1.2],
      [-1.7, 0.1, -0.4, 2.1, 0.5],
      [1.9, 2.3, -0.8, -0.7, 1.0],
      [-1.1, 2.8, -0.8, -0.3, 0.9]
    ]), [
      [-0.19393862606643053, -0.17101629636521865, 2.709348263225366, -0.0963000767188319, 0.5244718194343121],
      [0.38421326955977486, -0.21159588555260944, -6.544262021555474, -0.15113424769761136, -2.312533293658291],
      [-2.2708235174374747, 4.498279916441834, 1.4553799673144823, -0.9300926971755248, 2.5508111398452353],
      [-1.0935231387905004, 4.113817086842746, 5.747671819196675, -0.9408309030864932, 2.967655969930743]
    ]), 'fro') < 1e-3)
  })

  it('should solve sylvester equation of order 5 with Matrices', function () {
    assert.ok(math.norm(math.subtract(math.sylvester(math.matrix([
      [-5.3, -1.4, -0.2, 0.7],
      [-0.4, -1.0, -0.1, -1.2],
      [0.3, 0.7, -2.5, 0.7],
      [3.6, -0.1, 1.4, -2.4]
    ]), math.matrix([
      [1.1, -0.3, -0.9, 0.8, -2.5],
      [-0.6, 2.6, 0.2, 0.4, 1.3],
      [0.4, -0.5, -0.2, 0.2, -0.1],
      [-0.4, -1.9, -0.2, 0.5, 1.4],
      [0.4, -1.0, -0.1, -0.8, -1.3]
    ]), math.matrix([
      [1.4, 1.1, -1.9, 0.1, 1.2],
      [-1.7, 0.1, -0.4, 2.1, 0.5],
      [1.9, 2.3, -0.8, -0.7, 1.0],
      [-1.1, 2.8, -0.8, -0.3, 0.9]
    ])), math.matrix([
      [-0.19393862606643053, -0.17101629636521865, 2.709348263225366, -0.0963000767188319, 0.5244718194343121],
      [0.38421326955977486, -0.21159588555260944, -6.544262021555474, -0.15113424769761136, -2.312533293658291],
      [-2.2708235174374747, 4.498279916441834, 1.4553799673144823, -0.9300926971755248, 2.5508111398452353],
      [-1.0935231387905004, 4.113817086842746, 5.747671819196675, -0.9408309030864932, 2.967655969930743]
    ])), 'fro') < 1e-3)
  })

  it('should work with config legacySubset during deprecation', function () {
    const math2 = math.create()
    // Add a spy to temporarily disable console.warn
    const warnStub = sinon.stub(console, 'warn')

    math2.config({ legacySubset: true })

    // Test legacy syntax with sylvester
    // This is not strictly necessary and shoudl be removed after the deprecation period
    const sylvesterA = [[-5.3, -1.4, -0.2, 0.7],
      [-0.4, -1.0, -0.1, -1.2],
      [0.3, 0.7, -2.5, 0.7],
      [3.6, -0.1, 1.4, -2.4]]

    const sylvesterB = [
      [1.1, -0.3, -0.9, 0.8, -2.5],
      [-0.6, 2.6, 0.2, 0.4, 1.3],
      [0.4, -0.5, -0.2, 0.2, -0.1],
      [-0.4, -1.9, -0.2, 0.5, 1.4],
      [0.4, -1.0, -0.1, -0.8, -1.3]
    ]
    const sylvesterC = [
      [1.4, 1.1, -1.9, 0.1, 1.2],
      [-1.7, 0.1, -0.4, 2.1, 0.5],
      [1.9, 2.3, -0.8, -0.7, 1.0],
      [-1.1, 2.8, -0.8, -0.3, 0.9]
    ]

    const sylvesterSol = [
      [-0.19393862606643053, -0.17101629636521865, 2.709348263225366, -0.0963000767188319, 0.5244718194343121],
      [0.38421326955977486, -0.21159588555260944, -6.544262021555474, -0.15113424769761136, -2.312533293658291],
      [-2.2708235174374747, 4.498279916441834, 1.4553799673144823, -0.9300926971755248, 2.5508111398452353],
      [-1.0935231387905004, 4.113817086842746, 5.747671819196675, -0.9408309030864932, 2.967655969930743]
    ]
    assert.ok(math2.norm(math2.subtract(
      math2.sylvester(sylvesterA, sylvesterB, sylvesterC), sylvesterSol), 'fro') < 1e-3)

    // Test without legacySubset
    math2.config({ legacySubset: false })

    assert.ok(math2.norm(math2.subtract(
      math2.sylvester(sylvesterA, sylvesterB, sylvesterC), sylvesterSol), 'fro') < 1e-3)

    // Restore console.warn
    warnStub.restore()
  })
})
